﻿using System.IO;
using System.Text;

namespace Dapper.Sharding
{
    public class ConnectionStringBuilder
    {
        //https://mysqlconnector.net/connection-options/
        public static string BuilderMySql(DataBaseConfig config, string databaseName = null)
        {
            var sb = new StringBuilder();
            if (string.IsNullOrEmpty(config.Server))
            {
                config.Server = "127.0.0.1";
            }
            sb.Append($"server={config.Server}");
            if (config.Port != 0) //3306
            {
                sb.Append($";port={config.Port}");
            }
            if (string.IsNullOrEmpty(config.UserId))
            {
                config.UserId = "root";
            }
            sb.Append($";uid={config.UserId}");
            if (!string.IsNullOrEmpty(config.Password))
            {
                sb.Append($";pwd={config.Password}");
            }
            if (!string.IsNullOrEmpty(databaseName))
            {
                sb.Append($";database={databaseName}");
            }
            if (config.MinPoolSize != 0)
            {
                sb.Append($";min pool size={config.MinPoolSize}");
            }
            if (config.MaxPoolSize != 0)
            {
                sb.Append($";max pool size={config.MaxPoolSize}");
            }
            if (config.TimeOut != 0)
            {
                sb.Append($";connect timeout={config.TimeOut}");
            }
            if (config.CommandTimeout.HasValue && config.CommandTimeout.Value > 0)
            {
                sb.Append($";command timeout={config.CommandTimeout.Value}");
            }
            if (!string.IsNullOrEmpty(config.CharSet))
            {
                sb.Append($";charset={config.CharSet}");
            }
            if (!string.IsNullOrEmpty(config.OtherConfig))
            {
                sb.Append($";{config.OtherConfig}");
            }
            return sb.ToString();
        }

        public static string BuilderSqlServer(DataBaseConfig config, string databaseName = null)
        {
            var sb = new StringBuilder();
            if (string.IsNullOrEmpty(config.Server))
            {
                config.Server = ".";
            }
            sb.Append($"server={config.Server}");
            if (config.Port != 0) //1433
            {
                sb.Append($",{config.Port}");
            }
            if (string.IsNullOrEmpty(config.UserId))
            {
                config.UserId = "sa";
            }
            sb.Append($";uid={config.UserId}");

            if (!string.IsNullOrEmpty(config.Password))
            {
                sb.Append($";pwd={config.Password}");
            }
            if (!string.IsNullOrEmpty(databaseName))
            {
                sb.Append($";database={databaseName}");
            }
            if (config.MinPoolSize != 0)
            {
                sb.Append($";min pool size={config.MinPoolSize}");
            }
            if (config.MaxPoolSize != 0)
            {
                sb.Append($";max pool size={config.MaxPoolSize}");
            }
            if (config.TimeOut != 0)
            {
                sb.Append($";timeout={config.TimeOut}");
            }
            if (config.CommandTimeout.HasValue && config.CommandTimeout.Value > 0)
            {
                sb.Append($";command timeout={config.CommandTimeout.Value}");
            }
            if (config.TrustServerCertificate)
            {
                sb.Append(";TrustServerCertificate=true");
            }
            if (!string.IsNullOrEmpty(config.OtherConfig))
            {
                sb.Append($";{config.OtherConfig}");
            }
            return sb.ToString();
        }

        //https://www.npgsql.org/doc/connection-string-parameters.html
        public static string BuilderPostgresql(DataBaseConfig config, string databaseName = null)
        {
            var sb = new StringBuilder();
            if (string.IsNullOrEmpty(config.Server))
            {
                config.Server = "127.0.0.1";
            }
            sb.Append($"server={config.Server}");
            if (config.Port != 0) //5432
            {
                sb.Append($";port={config.Port}");
            }
            if (string.IsNullOrEmpty(config.UserId))
            {
                config.UserId = "postgres";
            }
            sb.Append($";uid={config.UserId}");
            if (!string.IsNullOrEmpty(config.Password))
            {
                sb.Append($";pwd={config.Password}");
            }
            if (!string.IsNullOrEmpty(databaseName))
            {
                sb.Append($";database={databaseName.ToLower()}");
            }
            if (config.MinPoolSize != 0)
            {
                sb.Append($";minpoolsize={config.MinPoolSize}");
            }
            if (config.MaxPoolSize != 0)
            {
                sb.Append($";maxpoolsize={config.MaxPoolSize}");
            }
            if (config.TimeOut != 0)
            {
                sb.Append($";timeout={config.TimeOut}");
            }
            if (config.CommandTimeout.HasValue && config.CommandTimeout.Value > 0)
            {
                sb.Append($";command timeout={config.CommandTimeout.Value}");
            }
            if (!string.IsNullOrEmpty(config.CharSet))
            {
                sb.Append($";encoding={config.CharSet}");
            }
            if (!string.IsNullOrEmpty(config.OtherConfig))
            {
                sb.Append($";{config.OtherConfig}");
            }
            return sb.ToString();
        }

        public static string BuilderOracleSysdba(DataBaseConfig config)
        {
            var sb = new StringBuilder();
            if (string.IsNullOrEmpty(config.Server))
            {
                config.Server = "127.0.0.1";
            }
            sb.Append($"data source={config.Server}");
            if (config.Port != 0) //1521
            {
                sb.Append($":{config.Port}");
            }
            if (string.IsNullOrEmpty(config.Oracle_ServiceName))
            {
                config.Oracle_ServiceName = "ORCL";
            }
            sb.Append($"/{config.Oracle_ServiceName}");
            sb.Append($";user id={config.Oracle_SysUserId}");
            if (!string.IsNullOrEmpty(config.Oracle_SysPassword))
            {
                sb.Append($";password={config.Oracle_SysPassword}");
            }
            if (config.MinPoolSize != 0)
            {
                sb.Append($";min pool size={config.MinPoolSize}");
            }
            if (config.MaxPoolSize != 0)
            {
                sb.Append($";max pool size={config.MaxPoolSize}");
            }
            if (config.TimeOut != 0)
            {
                sb.Append($";connect timeout={config.TimeOut}");
            }
            if (config.CommandTimeout.HasValue && config.CommandTimeout.Value > 0)
            {
                sb.Append($";command timeout={config.CommandTimeout.Value}");
            }
            sb.Append(";dba privilege=sysdba");
            if (!string.IsNullOrEmpty(config.OtherConfig))
            {
                sb.Append($";{config.OtherConfig}");
            }
            return sb.ToString();
        }

        public static string BuilderOracle(DataBaseConfig config, string userId = null)
        {
            var sb = new StringBuilder();
            if (string.IsNullOrEmpty(config.Server))
            {
                config.Server = "127.0.0.1";
            }
            sb.Append($"data source={config.Server}");
            if (config.Port != 0) //1521
            {
                sb.Append($":{config.Port}");
            }
            if (string.IsNullOrEmpty(config.Oracle_ServiceName))
            {
                config.Oracle_ServiceName = "ORCL";
            }
            sb.Append($"/{config.Oracle_ServiceName}");

            if (string.IsNullOrEmpty(userId) && string.IsNullOrEmpty(config.UserId))
            {
                throw new System.Exception("config.UserId and userId is null");
            }

            if (!string.IsNullOrEmpty(userId))
            {
                sb.Append($";user id={userId}");
            }
            else
            {
                sb.Append($";user id={config.UserId}");
            }

            if (!string.IsNullOrEmpty(config.Password))
            {
                sb.Append($";password={config.Password}");
            }
            else
            {
                if (!string.IsNullOrEmpty(userId))
                {
                    sb.Append($";password={userId}");
                }
                else
                {
                    sb.Append($";password={config.UserId}");
                }
            }
            if (config.MinPoolSize != 0)
            {
                sb.Append($";min pool size={config.MinPoolSize}");
            }
            if (config.MaxPoolSize != 0)
            {
                sb.Append($";max pool size={config.MaxPoolSize}");
            }
            if (config.TimeOut != 0)
            {
                sb.Append($";connect timeout={config.TimeOut}");
            }
            if (config.CommandTimeout.HasValue && config.CommandTimeout.Value > 0)
            {
                sb.Append($";command timeout={config.CommandTimeout.Value}");
            }
            if (!string.IsNullOrEmpty(config.OtherConfig))
            {
                sb.Append($";{config.OtherConfig}");
            }
            return sb.ToString();
        }

        public static string BuilderClickHouse(DataBaseConfig config, string databaseName = null)
        {
            var sb = new StringBuilder();
            if (string.IsNullOrEmpty(config.Server))
            {
                config.Server = "127.0.0.1";
            }
            sb.Append($"Host={config.Server}");
            if (config.Port == 0) //9000
            {
                config.Port = 8123;
            }
            sb.Append($";Port={config.Port}");
            if (string.IsNullOrEmpty(config.UserId))
            {
                config.UserId = "default";
            }
            sb.Append($";User={config.UserId}");
            if (!string.IsNullOrEmpty(config.Password))
            {
                sb.Append($";Password={config.Password}");
            }
            if (string.IsNullOrEmpty(databaseName))
            {
                databaseName = "default";
            }
            if (config.TimeOut != 0)
            {
                sb.Append($";Timeout={config.TimeOut}");
            }
            sb.Append($";Database={databaseName}");
            
            if (config.Compression)
            {
                sb.Append(";Compression=true");
            }
            else
            {
                sb.Append(";Compression=false");
            }

            if (config.ClickDecimal)
            {
                sb.Append(";UseCustomDecimals=true");
            }
            else 
            {
                sb.Append(";UseCustomDecimals=false");
            }

            if (config.ClickTimezone)
            {
                sb.Append(";UseServerTimezone=true");
            }
            else
            {
                sb.Append(";UseServerTimezone=false");
            }

            if (!string.IsNullOrEmpty(config.OtherConfig))
            {
                sb.Append($";{config.OtherConfig}");
            }
            return sb.ToString();
        }

        public static string BuilderSQLite(DataBaseConfig config, string databaseName = null)
        {
            var sb = new StringBuilder();
            if (!string.IsNullOrEmpty(config.Server))
            {
                sb.Append($"data source={Path.Combine(config.Server, databaseName)}");
            }
            //if (config.SQLite_CacheSize != 0)
            //{
            //    sb.Append($";Cache Size={config.SQLite_CacheSize}");
            //}
            //if (config.SQLite_PageSize != 0)
            //{
            //    sb.Append($";Page Size={config.SQLite_PageSize}");
            //}
            //if (config.MinPoolSize != 0 || config.MaxPoolSize != 0)
            //{
            //    sb.Append($";Pooling=True");
            //    if (config.MinPoolSize != 0)
            //    {
            //        sb.Append($";Min Pool Size={config.MinPoolSize}");
            //    }
            //    if (config.MaxPoolSize != 0)
            //    {
            //        sb.Append($";Max Pool Size={config.MaxPoolSize}");
            //    }

            //}
            //sb.Append($";Synchronous={config.SQLite_Synchronous}");
            if (config.CommandTimeout.HasValue && config.CommandTimeout.Value > 0)
            {
                sb.Append($";command timeout={config.CommandTimeout.Value}");
            }
            if (!string.IsNullOrEmpty(config.OtherConfig))
            {
                sb.Append($";{config.OtherConfig}");
            }
            return sb.ToString();
        }

        //https://duckdb.org/docs/configuration/overview.html
        //https://duckdb.net/docs/connection-string.html
        public static string BuilderDuckDb(DataBaseConfig config, string databaseName = null)
        {
            var sb = new StringBuilder();
            if (databaseName.Contains(":")) //内存数据库
            {
                sb.Append($"Data Source={databaseName}");
            }
            else //非内存数据库，数据存储再磁盘
            {
                if (!string.IsNullOrEmpty(config.Server))
                {
                    sb.Append($"Data Source={Path.Combine(config.Server, databaseName)}");
                }
            }
            if (config.Duck_Memory != 0)
            {
                sb.Append($";memory_limit={config.Duck_Memory}GB");
            }
            if (config.Duck_Threads != 0)
            {
                sb.Append($";threads={config.Duck_Threads}");
            }
            if (!string.IsNullOrEmpty(config.OtherConfig))
            {
                sb.Append($";{config.OtherConfig}");
            }
            return sb.ToString();
        }

        public static string BuilderSapHana(DataBaseConfig config, string databaseName = null)
        {
            var sb = new StringBuilder();
            if (string.IsNullOrEmpty(config.Server))
            {
                config.Server = "127.0.0.1";
            }
            sb.Append($"server={config.Server}");
            if (config.Port != 0)
            {
                sb.Append($":{config.Port}");
            }

            if (string.IsNullOrEmpty(config.UserId))
            {
                config.UserId = "SAPHANADB";
            }
            sb.Append($";uid={config.UserId}");

            if (!string.IsNullOrEmpty(config.Password))
            {
                sb.Append($";pwd={config.Password}");
            }

            if (!string.IsNullOrEmpty(databaseName))
            {
                sb.Append($";Current Schema={databaseName}");
            }

            if (config.TimeOut != 0)
            {
                sb.Append($";Connection Timeout={config.TimeOut}");
            }

            //if (config.CommandTimeout.HasValue)
            //{
            //    sb.Append($";communicationTimeout={config.CommandTimeout.Value}");
            //}

            if (config.MinPoolSize != 0)
            {
                sb.Append($";Min Pool Size={config.MinPoolSize}");
            }

            if (config.MaxPoolSize != 0)
            {
                sb.Append($";Max Pool Size={config.MaxPoolSize}");
            }

            if (config.HanaDecimal)
            {
                sb.Append(";return hanadecimal=true");
            }
            else
            {
                sb.Append(";return hanadecimal=false");
            }

            if (!string.IsNullOrEmpty(config.OtherConfig))
            {
                sb.Append($";{config.OtherConfig}");
            }
            return sb.ToString();
        }

    }
}
